﻿using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Timing;
using AutoMapper;
using MyABP.Authorization.Users;
using MyABP.Tasks.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq.Dynamic;
using Abp.Linq.Extensions;



using System.Data.Entity;
using Abp.Application.Services;
using Abp.Authorization;
using Abp.Extensions;
using Abp.Net.Mail.Smtp;
using Abp.Notifications;
using Abp.Runtime.Session;
using Abp.Threading;
using Abp.Events.Bus;
using Abp.Net.Mail;
using System.Linq.Dynamic.Core;
using MyABP.Authorization;
using Abp.UI;
using MyABP.Users.Dto;

namespace MyABP.Tasks
{
    /// <summary>
    /// Implements <see cref="ITaskAppService"/> to perform task related application functionality.
    /// 
    /// Inherits from <see cref="ApplicationService"/>.
    /// <see cref="ApplicationService"/> contains some basic functionality common for application services (such as logging and localization).
    /// </summary>
    public class TaskAppService : MyABPAppServiceBase, ITaskAppService
    {
        //These members set in constructor using constructor injection.

        private readonly IRepository<Task> _taskRepository;
        private readonly IRepository<User,long> _personRepository;

        /// <summary>
        ///In constructor, we can get needed classes/interfaces.
        ///They are sent here by dependency injection system automatically.
        /// </summary>
        public TaskAppService(IRepository<Task> taskRepository, IRepository<User,long> personRepository)
        {
            _taskRepository = taskRepository;
            _personRepository = personRepository;
        }

        public async Task<GetUserPermissionsForEditOutput> GetPermissions()
        {
            var user = await UserManager.GetUserByIdAsync(1);
            var permissions = PermissionManager.GetAllPermissions();
            var grantedPermissions = await UserManager.GetGrantedPermissionsAsync(user);

            return new GetUserPermissionsForEditOutput
            {
                Permissions = ObjectMapper.Map<List<FlatPermissionDto>>(permissions).OrderBy(p => p.DisplayName).ToList(),
                GrantedPermissionNames = grantedPermissions.Select(p => p.Name).ToList()
            };

        }


        public GetTasksOutput GetTasks(GetTasksInput input)
        {
            var query = _taskRepository.GetAllIncluding(t => t.AssignedPerson);

            if (input.AssignedPersonId.HasValue)
            {
                query = query.Where(t => t.AssignedPersonId == input.AssignedPersonId.Value);
            }

            if (input.State.HasValue)
            {
                query = query.Where(t => t.State == input.State.Value);
            }

            //Used AutoMapper to automatically convert List<Task> to List<TaskDto>.
            return new GetTasksOutput
            {
                Tasks = Mapper.Map<List<TaskDto>>(query.ToList())
            };
        }

        public async Task<TaskDto> GetTaskByIdAsync(int taskId)
        {
            //Called specific GetAllWithPeople method of task repository.
            var task = await _taskRepository.GetAsync(taskId);

            //Used AutoMapper to automatically convert List<Task> to List<TaskDto>.
            return task.MapTo<TaskDto>();
        }

        public TaskDto GetTaskById(int taskId)
        {
            var task = _taskRepository.Get(taskId);

            return task.MapTo<TaskDto>();
        }

        public void UpdateTask(UpdateTaskInput input)
        {
            //We can use Logger, it's defined in ApplicationService base class.
            Logger.Info("开始修改任务: " + input);

            //Retrieving a task entity with given id using standard Get method of repositories.
            //var task = _taskRepository.Get(input.Id);

            //Updating changed properties of the retrieved task entity.

            //if (input.State.HasValue)
            //{
            //    task.State =  input.State.Value;
            //}

            //if (input.AssignedPersonId.HasValue)
            //{
            //    task.AssignedPerson = _personRepository.Load(input.AssignedPersonId.Value);
            //}

            //获取当前用户
            var currentUser = AsyncHelper.RunSync(this.GetCurrentUserAsync);
            //获取是否有权限
            bool canAssignTaskToOther = PermissionChecker.IsGranted(PermissionNames.Pages_Tasks_AssignPerson);
            //如果任务已经分配且未分配给自己，且不具有分配任务权限，则抛出异常
            if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != currentUser.Id && !canAssignTaskToOther)
            {
                //throw new AbpAuthorizationException("没有分配任务给他人的权限！");
                throw new UserFriendlyException("没有分配任务给他人的权限！");
            }

            var task = Mapper.Map<Task>(input);
            _taskRepository.Update(task);

            //We even do not call Update method of the repository.
            //Because an application service method is a 'unit of work' scope as default.
            //ABP automatically saves all changes when a 'unit of work' scope ends (without any exception).
        }

        public string TestError()
        {

            try
            {
                int a = 1;
                int b = 0;
                int c = a / b;
                return "返回控制";
            }
            catch (Exception ex)
            {
                throw new UserFriendlyException("创建任务失败", ex.ToString());
            }
        }

        public int CreateTask(CreateTaskInput input)
        {
            try
            {


                //We can use Logger, it's defined in ApplicationService class.
                Logger.Info("Creating a task for input: " + input);

                //获取当前用户
                var currentUser = AsyncHelper.RunSync(this.GetCurrentUserAsync);

                //判断用户是否有权限
                //if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != currentUser.Id)
                //    PermissionChecker.Authorize(PermissionNames.Pages_Tasks_AssignPerson);

                //获取是否有权限
                bool canAssignTaskToOther = PermissionChecker.IsGranted(PermissionNames.Pages_Tasks_AssignPerson);
                //如果任务已经分配且未分配给自己，且不具有分配任务权限，则抛出异常
                if (input.AssignedPersonId.HasValue && input.AssignedPersonId.Value != currentUser.Id && !canAssignTaskToOther)
                {
                    //throw new AbpAuthorizationException("没有分配任务给他人的权限！");
                    throw new UserFriendlyException("没有分配任务给他人的权限！");
                }



                //Creating a new Task entity with given input's properties
                var task = new Task
                {
                    Description = input.Description,
                    Title = input.Title,
                    State = input.State,
                    CreationTime = Clock.Now
                };

                if (input.AssignedPersonId.HasValue)
                {
                    task.AssignedPerson = _personRepository.Load(input.AssignedPersonId.Value);
                }

                //Saving entity with standard Insert method of repositories.
                return _taskRepository.InsertAndGetId(task);
            }
            catch (Exception ex)
            {
                throw new UserFriendlyException("出错了", "新建任务出错了："+ex.Message);
            }
        }

        [AbpAuthorize(PermissionNames.Pages_Tasks_Delete)]
        public void DeleteTask(int taskId)
        {
            var task = _taskRepository.Get(taskId);
            if (task != null)
            {
                _taskRepository.Delete(task);
            }
        }

        public PagedResultDto<TaskDto> GetPagedTasks(GetTasksInput input)
        {
            //过滤
            var query = _taskRepository.GetAll().Include(p => p.AssignedPerson)
                        .WhereIf(input.State.HasValue, t => t.State == input.State.Value)
                        .WhereIf(!input.Filter.IsNullOrEmpty(), t => t.Title.Contains(input.Filter))
                        .WhereIf(input.AssignedPersonId.HasValue, t => t.AssignedPersonId == input.AssignedPersonId);

            //排序
            query = !string.IsNullOrEmpty(input.Sorting) ? query.OrderBy(input.Sorting) : query.OrderByDescending(t => t.CreationTime);


            //获取总数
            var tasksCount = query.Count();
            //默认的分页方式
            //var taskList = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList();

            //ABP提供了扩展方法PageBy分页方式
            var taskList = query.PageBy(input).ToList();

            return new PagedResultDto<TaskDto>(tasksCount, taskList.MapTo<List<TaskDto>>());
        }

        public IList<TaskDto> GetAllTasks()
        {
            throw new NotImplementedException();
        }
    }
}
